/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.ui.rich.full.command;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

import br.ufmg.dees.insane.commons.command.Command;
import br.ufmg.dees.insane.commons.controller.Controller;
import br.ufmg.dees.insane.model.geo.GCubicCurve;
import br.ufmg.dees.insane.model.geo.GCurve;
import br.ufmg.dees.insane.model.geo.GLine;
import br.ufmg.dees.insane.model.geo.GPoint;
import br.ufmg.dees.insane.model.geo.GQuadCurve;
import br.ufmg.dees.insane.ui.rich.full.InsaneInternalInterface;
import br.ufmg.dees.insane.ui.rich.full.controller.RegionController;

/**
 *
 * @author Pitangueira, Roque & Brugiolo, Marco & Fonseca, Flavio
 * @version 0.0.1 Beta
 */
public class AddCurveCommand implements Command, Cloneable {
    
    private InsaneInternalInterface parent;
    private Controller controller;
    private GCurve cv;
	
//*****************************************************************************
	
    /** Creates new AddCurveCommand */
    public AddCurveCommand(InsaneInternalInterface parent) {
		this.parent = (InsaneInternalInterface)parent;
		controller = this.parent.getController();
	}
	
//*****************************************************************************
	
    public void execute() {
		String message;
		ArrayList primit = controller.getSelection();
		ArrayList primitives = (ArrayList)primit.clone();
		int label = ((RegionController)controller).getLabelCurve();
		if ( primitives.size() > 0 ) {
			if ( isContinuos(primitives) ) {
				cv = new GCurve(label, primitives);
				
				Object obj = primitives.get(0);
				if (obj instanceof GPoint) {
					GPoint point = (GPoint)obj;
					cv.setFirstPoint(point.getP1() );
				}
				if (obj instanceof GLine) {
					GLine line = (GLine)obj;
					line.setIsFrame(false);
					cv.setFirstPoint(line.getP1() );
				}
				if (obj instanceof GQuadCurve) {
					GQuadCurve quad = (GQuadCurve)obj;
					quad.setIsFrame(false);
					cv.setFirstPoint(quad.getP1() );
				}
				if (obj instanceof GCubicCurve) {
					GCubicCurve cubic = (GCubicCurve)obj;
					cubic.setIsFrame(false);
					cv.setFirstPoint(cubic.getP1() );
				}
				
				obj = primitives.get(primitives.size() -1 );
				if (obj instanceof GPoint) {
					GPoint point = (GPoint)obj;
					cv.setEndPoint(point.getP2() );
				}
				if (obj instanceof GLine) {
					GLine line = (GLine)obj;
					cv.setEndPoint(line.getP2() );
				}
				if (obj instanceof GQuadCurve) {
					GQuadCurve quad = (GQuadCurve)obj;
					cv.setEndPoint(quad.getP2() );
				}
				if (obj instanceof GCubicCurve) {
					GCubicCurve cubic = (GCubicCurve)obj;
					cv.setEndPoint(cubic.getP2() );
				}
				
				message = parent.getResourceBundle().getString("cmCurve01")+ ", C" + cv.getLabel() + ":";
				ListIterator prs = primitives.listIterator();
				while(prs.hasNext()) {
					obj = prs.next();
					if (obj instanceof GPoint) {
						GPoint gp = (GPoint)obj;
						gp.setColor( ((RegionController)controller).getCurveColor() );
						message = message + " P" + gp.getLabel() + ",";
					}
					if (obj instanceof GLine) {
						GLine gl = (GLine)obj;
						gl.setColor( ((RegionController)controller).getCurveColor() );
						message = message + " P" + gl.getLabel() + ",";
					}
					if (obj instanceof GQuadCurve) {
						GQuadCurve gq = (GQuadCurve)obj;
						gq.setColor( ((RegionController)controller).getCurveColor() );
						message = message + " P" + gq.getLabel() + ",";
					}
					if (obj instanceof GCubicCurve) {
						GCubicCurve gc = (GCubicCurve)obj;
						gc.setColor( ((RegionController)controller).getCurveColor() );
						message = message + " P" + gc.getLabel() + ",";
					}
				}
				parent.getController().add(cv);
				parent.getDrawing().repaint();
			}else{
				controller.unSelectAll();
				parent.getDrawing().repaint();
				message = parent.getResourceBundle().getString("cmCurve02");
			}
		}else{
			message = parent.getResourceBundle().getString("gmSelectPrimitives");
		}
		
		parent.addOutputText(message);
		controller.unSelectAll();
	}
	
//*****************************************************************************
	
	public boolean isContinuos(List primitives) {
		if ( primitives.size() == 1 ) {
			return true;
		}
		
		Point2D pointLast = new Point2D.Double();
		Object obj = primitives.get(0);
		if (obj instanceof GPoint) {
			GPoint pointPrevious = (GPoint)obj;
			pointLast = pointPrevious.getP1();
		}
		if (obj instanceof GLine) {
			GLine linePrevious = (GLine)obj;
			pointLast = linePrevious.getP1();
		}
		if (obj instanceof GQuadCurve) {
			GQuadCurve quadPrevious = (GQuadCurve)obj;
			pointLast = quadPrevious.getP1();
		}
		if (obj instanceof GCubicCurve) {
			GCubicCurve cubicPrevious = (GCubicCurve)obj;
			pointLast = cubicPrevious.getP1();
		}
        ListIterator primit = primitives.listIterator();
        while(primit.hasNext()) {
            obj = primit.next();
			if (obj instanceof GPoint) {
				GPoint p = (GPoint)obj;
				Point2D p1 = p.getP1();
				if (isEqual(p1, pointLast) ) {
					pointLast = p.getP2();
				} else {
					return false;
				}
			}
			if (obj instanceof GLine) {
				GLine l = (GLine)obj;
				Point2D p1 = l.getP1();
				if (isEqual(p1, pointLast) ) {
					pointLast = l.getP2();
				}else{
					return false;
				}
			}
			if (obj instanceof GQuadCurve) {
				GQuadCurve q = (GQuadCurve)obj;
				Point2D p1 = q.getP1();
				if (isEqual(p1, pointLast) ) {
					pointLast = q.getP2();
				}else{
					return false;
				}
			}
			if (obj instanceof GCubicCurve) {
				GCubicCurve c = (GCubicCurve)obj;
				Point2D p1 = c.getP1();
				if (isEqual(p1, pointLast) ) {
					pointLast = c.getP2();
				}else{
					return false;
				}
			}
        }
		
		return true;
	}
	
//*****************************************************************************
	
	public boolean isEqual(Point2D p1, Point2D p2) {
		if (p1.getX() != p2.getX() ) {
			return false;
		} else {
			if (p1.getY() != p2.getY() ) {
				return false;
			}else{
				return true;
			}
		}
	}
	
//*****************************************************************************
	
	/** Impossible to undo - Not implemented */
	public void undo() {}
	
//*****************************************************************************
	
	/** Impossible to redo - Not implemented */
	public void redo() {}
	
//*****************************************************************************
}

